#pragma once

#include <functional>
#include <thread>
#include <memory>
#include <mutex>
#include "Poller.h"
#include "Channel.h"
#include "TimerWheel.h"

class EventLoop
{
private:
    using Functor = std::function<void()>;
    std::thread::id _thread_id;              // 线程id，记录当前EventLoop是被哪一个线程的id创建的，标识当前EventLoop所属线程id
    int _eventfd;                            // 事件通知描述符，防止其他文件描述符没有事件，那么就用这个文件描述符唤醒线程
    std::unique_ptr<Channel> _event_channel; // 把_eventfd也注册到Channel里面去
    Poller _poller;                          // 用于进行所有文件描述符的事件监控
    std::vector<Functor> _tasks;             // 任务池
    std::mutex _mutex;                       // 保证多线程对任务池进的线程安全
    TimerWheel _timer_wheel;

public:
    // 1. 执行任务池中的所有任务
    void RunAllTask();

    // 2. 创建一个事件通知描述符
    static int CreateEventFd();

    // 3. 读取事件通知描述符
    void ReadEvent();

    // 4. 向_eventfd中写入数据，唤醒IO事件
    void WeakUpEventFd();

public:
    EventLoop();

    // 1. 运行当前任务
    void RunInLoop(const Functor &cb);

    // 2. 将任务压入任务池
    void QueueInLoop(const Functor &cb);

    // 3. 判断当前线程是否是EventLoop对应的线程
    bool IsInLoop();

    // 4. 添加/修改描述符的事件监控
    void UpdataEvent(Channel *channel);

    // 5. 移除描述符的事件监控
    void RemoveEvent(Channel *channel);

    // 6. 添加定时任务
    void TimerAdd(uint64_t id, uint32_t delay, const TaskFunc &cb);

    // 7. 刷新当前定时任务在时间轮的位置
    void TimerRefresh(uint64_t id);

    // 8. 取消定时任务
    void TimerCancel(uint64_t id);

    bool HasTimer(uint64_t id);

    // 10. 启动事件循环
    void Start();
};